<template>
  <Table :columns="columns" :data-source="items" :scroll="{ x: 500, y: height - 45 }" :pagination="false" size="small" bordered>
    <template #bodyCell="{ column, record, index }">
      <div :key="record.index + ''" class="editable-cell-text-wrapper" v-if="column.key == 'key'">
        <Input v-model:value="editableData[record.index].key" placeholder="请输入键" />
      </div>
      <template v-if="column.key == 'value'">
        <Select v-if="record.items" v-model:value="editableData[record.index].value" style="width: 100%">
          <Select.Option v-for="item of record.items" :value="item.value">{{ item.text }}</Select.Option>
        </Select>
        <Input v-else v-model:value="editableData[record.index].value" placeholder="请输入值" />
      </template>
      <span v-if="column.key == 'op'" class="btn-group">
        <Button type="primary" @click="append(record.index)"><PlusCircleFilled /></Button>
        <Button type="primary" shape="round" danger @click="remove(record && record.index)"><DeleteOutlined /></Button>
      </span>
    </template>
  </Table>
</template>
<script setup>
  import { ref, onMounted, watch, reactive } from 'vue';
  import { Table, Input, Select, Button } from 'ant-design-vue';
  import { PlusCircleFilled, DeleteOutlined } from '@ant-design/icons-vue';

  const props = defineProps({
    items: {
      type: Array,
      default() {
        return [
          {
            key: '',
            value: '',
            description: '',
            checked: false
          }
        ];
      }
    },
    height: {
      type: Number,
      default() {
        return 400;
      }
    }
  });

  const emits = defineEmits(['update:items']);

  const columns = [
    { title: '键', width: 60, key: 'key' },
    { title: '值', width: 140, key: 'value' },
    { key: 'op', width: 55, align: 'left' }
  ];

  const rowIndex = ref(0);
  const items = ref([]);
  const editableData = reactive({});

  watch(
    items,
    () => {
      if (items.value.length == 1) {
        rowIndex.value = 0;

        let props = Object.keys(editableData);

        if (props.length > 0) {
          editableData[props[0]].index = 0;
          editableData[props[0]].key = '';
          editableData[props[0]].value = '';

          if (props.length > 1) {
            for (let index = 1; index < props.length; index++) {
              delete editableData[props[index]];
            }
          }
        }
      }

      items.value.forEach((item, index) => {
        let finded = true;

        if (item.index == undefined) {
          item.index = rowIndex.value;

          finded = false;
          rowIndex.value = rowIndex.value + 1;
        }

        let eitem = editableData[item.index];

        if (finded && eitem && eitem.key) {
          item.key = eitem.key;
          item.value = eitem.value;
        }

        editableData[item.index] = { index: item.index, key: item.key, value: item.value };
      });

      for (let key in editableData) {
        if (items.value.findIndex(v => v.index == key) == -1) {
          delete editableData[key];
        }
      }
    },
    { deep: true }
  );

  onMounted(() => {
    if (items.value.length == 0) {
      rowIndex.value = 0;
      items.value.push({ index: rowIndex.value, key: '', value: '' });

      rowIndex.value = rowIndex.value + 1;
    } else {
      items.value.forEach(i => {
        i.index = rowIndex.value;
        rowIndex.value = rowIndex.value + 1;
      });
    }

    emits('update:items', items.value);
  });

  function append(index) {
    let realIndex = items.value.findIndex(v => v.index == index);

    rowIndex.value = rowIndex.value + 1;
    items.value.splice(realIndex + 1, 0, { index: rowIndex.value, key: '', value: '' });

    emits('update:items', items.value);
  }

  function remove(index) {
    if (items.value.length == 1) {
      let current = items.value[0];

      current.index = 0;
      current.key = '';
      current.value = '';
      current.description = '';
    } else {
      try {
        let realIndex = items.value.findIndex(v => v.index == index);

        items.value.splice(realIndex, 1);
      } catch (err) {
        console.error(err);
      }
    }

    emits('update:items', items.value);
  }

  function build() {
    let rs = {};

    for (let key in editableData) {
      let item = editableData[key];

      if (item.key && rs.ig != true) {
        rs[item.key] = item.value;
      }
    }

    return rs;
  }

  function getFullValues() {
    let rs = {};

    for (let key in editableData) {
      let item = editableData[key];

      rs[item.key] = item.value;
    }

    return rs;
  }

  defineExpose({ build, getFullValues });
</script>
<style lang="less"></style>
